package com.flyxiaozhu.erp.core.interceptors;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.flyxiaozhu.erp.core.entities.App;
import com.flyxiaozhu.erp.core.libs.ErrorCode;
import com.flyxiaozhu.erp.core.libs.JSONResult;
import com.flyxiaozhu.erp.core.repositories.AppRepository;
import com.flyxiaozhu.erp.core.services.SignatureService;
import com.flyxiaozhu.erp.core.annotations.RequireSignature;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 配置拦截器
 */
@Service
public class SignatureInterceptor implements HandlerInterceptor {
    @Value("${app.sign.enable}")
    private String enable;

    @Value("${app.sign.field-name.key}")
    private String fieldNameKey;

    @Value("${app.sign.field-name.appid}")
    private String fieldNameAppId;

    @Autowired
    SignatureService signatureService;

    @Autowired
    AppRepository appRepository;

    /**
     * 请求前执行，返回false，则请求不执行
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (enable != null && enable.equals("false")) {
            return true;
        }

        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        Annotation methodAnno = method.getAnnotation(RequireSignature.class); // 获取方法上的RequireSignature注解
        if (methodAnno != null && !((RequireSignature) methodAnno).value()) {
            return true;
        } else {
            Class cls = method.getDeclaringClass();// 获取该方法的类的对象
            Annotation clsAnno = cls.getAnnotation(RequireSignature.class);
            if (clsAnno != null && !((RequireSignature) clsAnno).value()) {
                return true;
            }
        }

        // 进行签名验证
        String key = request.getParameter(fieldNameKey);
        Long appId;
        try {
            appId = Long.valueOf(request.getParameter(fieldNameAppId));
        } catch (NumberFormatException e) {
            renderError(response, new JSONResult(ErrorCode.SIGN_ERROR, "签名appid错误"));
            return false;
        }

        if (appId <= 0) {
            renderError(response, new JSONResult(ErrorCode.SIGN_ERROR, "签名appid错误"));
            return false;
        }

        App app = appRepository.findById(appId).orElse(null);
        if (app == null) {
            renderError(response, new JSONResult(ErrorCode.SIGN_ERROR, "签名appid错误"));
            return false;
        }

        if (StringUtils.isBlank(key) || !key.equals(app.getKey())) {
            renderError(response, new JSONResult(ErrorCode.SIGN_ERROR, "签名key错误"));
            return false;
        }

        if (signatureService.verify(request, app.getSecret())) {
            return true;
        } else {
            renderError(response, new JSONResult(ErrorCode.SIGN_ERROR, "签名错误"));
            return false;
        }
    }


    private void renderError(HttpServletResponse response, JSONResult result) throws IOException {
        response.setContentType("application/json; charset=utf-8");
        response.getWriter().write(new ObjectMapper().writeValueAsString(result));
        response.getWriter().close();
    }
}
